#include <QtXml>
#include <QFile>
#include <QDir>
#include <QSet>
#include <QDebug>
#include <QTextStream>
#include "TagMaster.h"
#include "ORM/Tag.h"

typedef QXmlStreamReader::TokenType TokenType;

TagMaster::TagMaster()
{
    createNewDocument();
}

TagMaster::~TagMaster()
{
    clear();
}

bool TagMaster::isNull()
{
    return m_document.isNull();
}

void TagMaster::createNewDocument()
{
    clear();

    QDomElement master = m_document.createElement("master");
    m_tags = m_document.createElement(TagList::tagName());
    m_relations = m_document.createElement(RelationList::tagName());
    m_entry = m_document.createElement(Entry::tagName());
    m_lostAndFound = m_document.createElement(LostAndFound::tagName());

    master.setAttribute("version", qApp->applicationVersion());
    master.setAttribute("editor", qApp->applicationName());
    master.setAttribute("date", QDateTime::currentDateTimeUtc().toString(Qt::ISODate));

    m_document.appendChild(m_document.createProcessingInstruction("xml", R"(version="1.0" encoding="utf-8")"));
    m_document.appendChild(master);
    master.appendChild(m_tags);
    master.appendChild(m_relations);
    master.appendChild(m_entry);
    master.appendChild(m_lostAndFound);

}

bool TagMaster::setFileTag(const QString &filePath, quint64 fileSize, const QString &qs)
{
    QStringList nameList = QDir::fromNativeSeparators(filePath).split("/", QString::SkipEmptyParts);
    QDomElement current = m_entry;

    for (int i = 0; i < nameList.size() - 1; i++) {
        QDomNodeList childNodes = current.childNodes();
        bool exist = false;
        for (int j = 0; j < childNodes.size(); j++) {
            QDomElement dirElement = childNodes.item(j).toElement();
            if (!dirElement.isNull() && dirElement.tagName() == "dir" && dirElement.attribute("name") == nameList[i]) {
                current = dirElement;
                exist = true;
                break;
            }
        }
        if (!exist) {
            QDomElement dirElement = m_document.createElement("dir");
            dirElement.setAttribute("name", nameList[i]);
            current.appendChild(dirElement);
            current = dirElement;
        }
    }

    QDomNodeList childNodes = current.childNodes();
    QDomElement existedFileElement;
    bool exist = false;
    for (int j = 0; j < childNodes.size(); j++) {
        QDomElement fileElement = childNodes.item(j).toElement();
        if (!fileElement.isNull() && fileElement.tagName() == "file" && fileElement.attribute("name") == nameList.last()) {
            exist = true;
            existedFileElement = fileElement;
            break;
        }
    }
    QDomElement fileElement  = m_document.createElement("file");
    fileElement.setTagName("file");
    fileElement.setAttribute("name", nameList.last());
    fileElement.setAttribute("size", fileSize);
    fileElement.setAttribute("qs", qs);

    if (exist) {
        current.replaceChild(fileElement, existedFileElement);
    } else {
        current.appendChild(fileElement);
    }

    return true;

}

bool TagMaster::openXmlFile(const QString &path)
{
    clear();

    m_xmlSavePath = path;
    QFile xmlFile(path);
    bool ret;
    if (xmlFile.open(QIODevice::ReadOnly)) {
        ret = m_document.setContent(&xmlFile);
    } else {
        ret = false;
    }

    if (!ret) {
        clear();
    }

    m_tags = m_document.documentElement().firstChildElement(TagList::tagName());
    m_relations = m_document.documentElement().firstChildElement(RelationList::tagName());
    m_entry = m_document.documentElement().firstChildElement(Entry::tagName());
    m_lostAndFound = m_document.documentElement().firstChildElement(LostAndFound::tagName());

    return ret;
}

void TagMaster::setXmlFileSavePath(const QString &path)
{
    m_xmlSavePath = path;
}

TagList TagMaster::tags()
{
    return TagList(m_tags);
}

RelationList TagMaster::relations()
{
    return RelationList(m_relations);
}

Entry TagMaster::entry()
{
    return Entry(m_entry);
}

bool TagMaster::save()
{
    return saveXmlFileAs(m_xmlSavePath);
}

bool TagMaster::saveXmlFileAs(const QString &path)
{
    bool ret = false;
    QFile xmlFile(path);
    if (xmlFile.open(QIODevice::WriteOnly)) {
        QTextStream stream(&xmlFile);
        stream.setCodec("UTF-8");
        stream << m_document.toString(4);
        ret = true;
    }
    return ret;
}

QString TagMaster::xmlFileSavePath()
{
    return m_xmlSavePath;
}

void TagMaster::clear()
{
    m_xmlSavePath.clear();
    m_entryPath.clear();
    m_tags.clear();
    m_relations.clear();
    m_entry.clear();
    m_lostAndFound.clear();
    m_document.clear();
}

